package com.alibaba.fastjson;

import java.lang.reflect.Array;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.util.*;

import com.alibaba.fastjson.util.GsonUtil;
import com.alibaba.fastjson.util.TypeUtils;

/**
 * Json 解析类，里面包含了主要的 Json 解析方法
 * 这是fastjson临时方案，请使用gson
 */
@Deprecated
public abstract class JSON {

//    private static final long serialVersionUID = -6384011134581682188L;
    protected static final TimeZone defaultTimeZone = TimeZone.getDefault();
    protected static final String DEFAULT_TYPE_KEY = "@type";
    protected static final String DEFFAULT_DATE_FORMAT = "yyyy-MM-dd HH:mm:ss";
    protected static final Locale defaultLocale = Locale.getDefault();

    public static Object parse(String text) {
        return GsonUtil.fromJson(text);
    }


    public static JSONObject parseObject(String text) {
        return GsonUtil.fromJson(text, JSONObject.class);
    }

    public static <T> T parseObject(String text, Class<T> clazz) {
        return GsonUtil.fromJson(text, clazz);
    }

    public static JSONArray parseArray(String text) {
        return GsonUtil.from(text, JSONArray.class);
    }

    public static <T> List<T> parseArray(String text, Class<T> clazz) {
        return GsonUtil.jsonToList(text, clazz);
    }

    public static String toJSONString(Object object) {
        return GsonUtil.toJson(object);
    }

    @Override
    public String toString() {
        return toJSONString();
    }


    public String toJSONString() {
        return GsonUtil.toJson(this);
    }


    public static String toString(Object object) {
        return toJSONString(object);
    }


    public static <T> T toJavaObject(String json, Class<T> clazz) {
        return GsonUtil.fromJson(json, clazz);
    }

    private final static ThreadLocal<byte[]> bytesLocal = new ThreadLocal<byte[]>();

    private static byte[] allocateBytes(int length) {
        byte[] chars = bytesLocal.get();

        if (chars == null) {
            if (length <= 1024 * 64) {
                chars = new byte[1024 * 64];
                bytesLocal.set(chars);
            } else {
                chars = new byte[length];
            }
        } else if (chars.length < length) {
            chars = new byte[length];
        }

        return chars;
    }

    private final static ThreadLocal<char[]> charsLocal = new ThreadLocal<char[]>();

    private static char[] allocateChars(int length) {
        char[] chars = charsLocal.get();

        if (chars == null) {
            if (length <= 1024 * 64) {
                chars = new char[1024 * 64];
                charsLocal.set(chars);
            } else {
                chars = new char[length];
            }
        } else if (chars.length < length) {
            chars = new char[length];
        }

        return chars;
    }


    /**
     * jackson parse出来的是map和list,所以把map和list转换为jsonObject和jsonArray
     *
     * @param map
     * @return
     */
    private static JSONObject mapToJsonObject(Map<String, Object> map) {
        JSONObject jsonObject = new JSONObject();
        for (Map.Entry<String, Object> entry : map.entrySet()) {
            final Object value = entry.getValue();
            if (value instanceof Map) {
                jsonObject.put(entry.getKey(), mapToJsonObject((Map<String, Object>) value));
            } else if (value instanceof List) {
                final List listVal = (List) value;
                JSONArray objects = new JSONArray();
                for (Object o : listVal) {
                    if (o instanceof Map) {
                        objects.add(mapToJsonObject((Map<String, Object>) o));
                    } else if (o instanceof List) {
                        objects.add(listConvertToJsonArray((List) o));
                    }
                }
                jsonObject.put(entry.getKey(), objects);
            } else {
                jsonObject.set(entry.getKey(), value);
            }
        }
        return jsonObject;
    }

    public static JSONArray listConvertToJsonArray(List list) {
        List<Object> jsonObjects = new ArrayList<>(list.size());
        for (Object obj : list) {
            jsonObjects.add(mapToJsonObject((Map<String, Object>) obj));
        }
        return new JSONArray(jsonObjects);
    }

    public static Object toJSON(Object javaObject) {
        if (javaObject == null) {
            return null;
        }

        if (javaObject instanceof JSON) {
            return javaObject;
        }

        if (javaObject instanceof Map) {
            Map<Object, Object> map = (Map<Object, Object>) javaObject;

            int size = map.size();

            Map innerMap;
            if (map instanceof LinkedHashMap) {
                innerMap = new LinkedHashMap(size);
            } else if (map instanceof TreeMap) {
                innerMap = new TreeMap();
            } else {
                innerMap = new HashMap(size);
            }

            JSONObject json = new JSONObject(innerMap);

            for (Map.Entry<Object, Object> entry : map.entrySet()) {
                Object key = entry.getKey();
                String jsonKey = TypeUtils.castToString(key);
                Object jsonValue = toJSON(entry.getValue());
                json.put(jsonKey, jsonValue);
            }

            return json;
        }

        if (javaObject instanceof Collection) {
            Collection<Object> collection = (Collection<Object>) javaObject;

            JSONArray array = new JSONArray(collection.size());

            for (Object item : collection) {
                Object jsonValue = toJSON(item);
                array.add(jsonValue);
            }

            return array;
        }

        Class<?> clazz = javaObject.getClass();

        if (clazz.isEnum()) {
            return ((Enum<?>) javaObject).name();
        }

        if (clazz.isArray()) {
            int len = Array.getLength(javaObject);

            JSONArray array = new JSONArray(len);

            for (int i = 0; i < len; ++i) {
                Object item = Array.get(javaObject, i);
                Object jsonValue = toJSON(item);
                array.add(jsonValue);
            }

            return array;
        }

        return GsonUtil.from(javaObject.toString(), JSONObject.class);

    }


}
